package com.zack.util.nlp.segment;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.HashSet;

/**
 * Created by simonpeng on 17/1/25.
 */
public class BaseAnalyzer {
    /**
     * 是否全中文字符串
     */
    public static boolean isCh(String input) {
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (!(ch >= 0x4E00 && ch <= 0x9FA5)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 是否有中文字符串
     */
    public static boolean hasCh(String input) {
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if ((ch >= 0x4E00 && ch <= 0x9FA5)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否全英文字符串
     */
    public static boolean isEn(String input) {
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 去除首位的非字母以及汉字字符（加强版的trim）
     */
    public static String strong_trim(String input) {
        StringBuilder strBuilder = new StringBuilder(input);
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if ((ch >= 0x4E00 && ch <= 0x9FA5) || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z')) {
                break;
            } else {
                strBuilder.setCharAt(i, ' ');
            }
        }
        for (int i = len - 1; i >= 0; --i) {
            char ch = input.charAt(i);
            if ((ch >= 0x4E00 && ch <= 0x9FA5) || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z')) {
                break;
            } else {
                strBuilder.setCharAt(i, ' ');
            }
        }
        return strBuilder.toString().trim();
    }

    /**
     * 繁体转简体
     */
    public static String CnT2S(String input) {
        StringBuilder sb = new StringBuilder();
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (CnT2SDict.T2S_Dict.containsKey(ch)) {
                sb.append(CnT2SDict.T2S_Dict.get(ch));
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    /**
     * 汉字转拼音
     */
    public static String CnC2P(String input) {
        StringBuilder sb = new StringBuilder();
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (CnC2PDict.C2P_Dict.containsKey(ch)) {
                sb.append(CnC2PDict.C2P_Dict.get(ch).get(0));
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    /**
     * 汉字转拼音前缀
     */
    public static String CnC2Prefix(String input) {
        StringBuilder sb = new StringBuilder();
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (CnC2PDict.C2P_Dict.containsKey(ch)) {
                sb.append(CnC2PDict.C2P_Dict.get(ch).get(0).charAt(0));
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    /**
     * 半角 to 全角
     */
    public static String B2Q(String input) {
        StringBuilder sb = new StringBuilder();
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (ch == 0x20) {
                ch = 0x3000;
            } else if (ch > 0x20 && ch < 0x7F) {
                ch = (char) (ch + 0xFEE0);
            } else {
            }
            sb.append(ch);
        }
        return sb.toString().trim();
    }

    /**
     * 全角 to 半角
     */
    public static String Q2B(String input) {
        StringBuilder sb = new StringBuilder();
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            if (ch == 0x3000) {
                ch = 0x20;
            } else if (ch > 0xFF00 && ch < 0xFF5F) {
                ch -= 0xFEE0;
            } else {
            }
            sb.append(ch);
        }
        return sb.toString().trim();
    }

    /**
     * 全角转半角、大写转小写，基础归一化、保留手写输错的各种字符
     */
    /* ========【函数功能】QC等处理时调用 ========== */
    public static String regularize_base(String input) {
        StringBuilder sb = new StringBuilder();
        int len = input.length();
        boolean is_last_whitespace = false;
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            // 1、全角字符转成半角
            if (ch == 0x3000) {// 全角空格转半角空格
                ch = 32;
            } else if (ch > 0xFF00 && ch < 0xFF5F) {// 全角Anscii符号、字母转半角
                ch -= 0xFEE0;
            } else {
            }
            // 2、大写字母转小写字母
            if (ch >= 'A' && ch <= 'Z') {// 大写转小写
                ch += 32;
            }
            if (!is_last_whitespace || ch != 32) {// 不是行首或前面已有空格，可以输出空格
                sb.append(ch);
            }
            if (ch == 32) {
                is_last_whitespace = true;
            } else {
                is_last_whitespace = false;
            }
        }
        return sb.toString().trim();
    }

    public static final HashSet<Character> SegRemainsSymbols = new HashSet<Character>();
    public static final HashSet<Character> GenericRemainsSymbols = new HashSet<Character>();
    static {
        SegRemainsSymbols.clear();
        SegRemainsSymbols.add('-');
        SegRemainsSymbols.add('+');
        SegRemainsSymbols.add('.');// 表示计量单位
        SegRemainsSymbols.add('*');// 表示计量时10*10经常需要Seg
        SegRemainsSymbols.add('%');// 表示计量时10*10经常需要Seg
        SegRemainsSymbols.add('/');
        SegRemainsSymbols.add('#');

        GenericRemainsSymbols.clear();
    }

    /****************************************************************************
     * 1、符号处理：361。、250*200，3+2饼干、100%、手机支架9.9、需要在分词时考虑；
     * 2、需要列出有特殊需求如KISS+ME作为一个词表的、标点符号不能随意去除；
     ***************************************************************************/
    /* ========【函数功能】分词时调用，保留部分需要的连接字符字符和部分特殊字符========== */
    public static String regularize_common_seg(String input) {
        return regularize_common(input, BaseAnalyzer.SegRemainsSymbols);
    }

    /* ========【函数功能】suggest时调用、特殊处理时调用，对比分词时，符号字符去除多一些= */
    public static String regularize_common_sug(String input) {
        return regularize_common(input, BaseAnalyzer.GenericRemainsSymbols);
    }

    /****************************************************************************
     * 全角转半角、大写转小写、标点符号去除（有要求的常用连接符号进行保留）
     ***************************************************************************/
    private static String regularize_common(String input, HashSet<Character> remainsSymbols) {
        StringBuilder sb = new StringBuilder();
        boolean is_last_whitespace = false;
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            // 1、全角字符转成半角
            if (ch == 0x3000) {// 全角空格转半角空格
                ch = 32;
            } else if (ch > 0xFF00 && ch < 0xFF5F) {// 全角Anscii符号、字母转半角
                ch -= 0xFEE0;
            } else {
            }

            // 2、汉字【包括4E00-9FA5中日韩统一表意文字之外的其他中日韩扩展字符】、数字、字母直接输出
            // 这一步放在前面提高效率
            if ((ch >= 0x4E00 && ch <= 0x9FA5) || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z')) {
                sb.append(ch);
                is_last_whitespace = false;
            }
            // 3、大写字母转小写字母输出
            else if (ch >= 'A' && ch <= 'Z') {
                ch += 32;
                sb.append(ch);
                is_last_whitespace = false;
            }
            // 标点符号去除以空格替换、多个空格合并成一个：http://blog.csdn.net/shuilan0066/article/details/7839270
            else if (((/* ch != 32 && */ch < 0x00FF) || /* ASCII码表中标点符号，包含空格 */
                    (ch >= 0x2000 && ch <= 0x206F) || /* 通用标点符号 */
                    (ch >= 0x3000 && ch <= 0x303F) || /* 中日韩标点符号 */
                    (ch >= 0xFFF0 && ch <= 0xFFFF) || /* 特殊 (Specials) */
                    (ch >= 0xFE00 && ch <= 0xFE0F) || /* 变体选择符 */
                    // (ch >= 0x0300 && ch <= 0x036F) || /*组合音标*/
                    // (ch >= 0x20D0 && ch <= 0x20FF) || /*符号组合音标*/
                    // (ch >= 0xD800 && ch <= 0xDFFF) || /*高低位代理区*/
                    (false)) && !remainsSymbols.contains(ch)) {
                ch = 32;
                if (!is_last_whitespace && i != 0 && i != len - 1) {// 不是行首或前面已有空格，可以输出空格
                    is_last_whitespace = true;
                    sb.append(ch);
                }
            }
            // 其他未知字符直接输出
            else {
                sb.append(ch);
                is_last_whitespace = false;
            }
        }
        return sb.toString().trim();
    }

    /**
     * 全角转半角、大写转小写、非中、英文字符全部去除
     */
    private static String regularize_strict(String input) {
        StringBuilder sb = new StringBuilder();
        boolean is_last_whitespace = false;
        int len = input.length();
        for (int i = 0; i < len; ++i) {
            char ch = input.charAt(i);
            // 1、全角字符转成半角
            if (ch == 0x3000) {// 全角空格转半角空格
                ch = 32;
            } else if (ch > 0xFF00 && ch < 0xFF5F) {// 全角Anscii符号、字母转半角
                ch -= 0xFEE0;
            } else {
            }

            // 2、汉字、数字、字母直接输出：http://blog.csdn.net/shuilan0066/article/details/7839189
            if ((ch >= 0x4E00 && ch <= 0x9FA5) || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z')) {
                sb.append(ch);
                is_last_whitespace = false;
            }
            // 3、大写字母转小写字母输出
            else if (ch >= 'A' && ch <= 'Z') {
                ch += 32;
                sb.append(ch);
                is_last_whitespace = false;
            } else {// 其他所有字符去除、以空格替换，多个空格合并成一个
                ch = 32;
                if (!is_last_whitespace && i != 0 && i != len - 1) {// 不是行首或前面已有空格，可以输出空格
                    is_last_whitespace = true;
                    sb.append(ch);
                }
            }
        }
        return sb.toString().trim();
    }

    public static void main(String[] args) {
        testCase(args);
    }

    public static void testCase(String[] args) {
        try {
            System.out.println(BaseAnalyzer.isEn("Cdgaosdash"));
            System.out.println(BaseAnalyzer.isCh("中华"));
            System.out.println(BaseAnalyzer.CnC2Prefix("中华"));
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    new FileInputStream("/Users/simonpeng/Desktop/pdd-doc/43-Suggest/query.stat.10w"), "UTF-8"));
            String line = null;
            int count = 0;
            int count_md = 0;
            System.out.println("start time: " + new Date());
            while ((line = br.readLine()) != null) {
                try {
                    count++;
                    // str = BaseAnalyzer.regularize(line);
                    String items[] = line.split("\t");
                    String term = items[1];
                    // String str1 =regularize_common(term, GenericRemainsSymbols);
                    String str1 = regularize_common_seg(term);
                    String str2 = regularize_common_sug(term);
                    if (!str1.equals(str2)) {
                        System.out.println(line + "///" + str1 + "///" + str2);
                        count_md++;
                    }
                } catch (Exception e) {
                    // System.out.println(line);
                    continue;
                }
            }
            System.out.println("end time: " + new Date());
            System.out.println(count + " ======= " + count_md);
            br.close();
            System.out.println("total process " + (count) + " docs");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}
